//=============================================================================
/**
 *
 *	@file		catch_sub.c
 *	@brief		UFOキャッチ 上画面処理
 *	@author		hosaka genya
 *	@data		2008.12.15
 *
 */
//=============================================================================
#include "common.h"
#include "system/clact_tool.h"
#include "system/msgdata_util.h"
#include "system/wordset.h"
#include "system/fontproc.h"
#include "system/snd_tool.h"

#include "../../pkthln_comm_pack.h"
#include "../../pkthln_obj_common.h"
#include "../../pokethlon.h"
#include "../event_se_def.h"

#include "catch_define.h"
#include "catch_sub.h"

//=============================================================================
/**
 *								定数定義
 */
//=============================================================================
enum
{
	TIME_PAL_OFS  = 1,
	TIME_CAP_DIFF_X = 4,	///< 時間アイコンと時間表記の間ドット
	TIME_ICON_POS_X = 27*8 - 2 - TIME_CAP_DIFF_X,
	TIME_ICON_POS_Y = 9*8 + 4,

};

#define POINT_NUMBER_W	(4)			//数字横キャラ幅
#define POINT_NUMBER_H	(8)			//数字縦キャラ幅
#define POINT_DIGI_MAX	(3)			//得点は最大3桁
#define POINT_DISP_START_X	(0)		//数描画開始X位置（キャラ）
#define POINT_DISP_START_Y	(0)		//数描画開始Y位置（キャラ）
#define NUMBER_SCR_NUM_W	(5)		//数字スクリーンデータの横の数字の数0〜4	スクリーンデータに依存
#define NUMBER_SCR_NUM_H	(2)		//数字スクリーンデータの縦の数字の数5〜9	スクリーンデータに依存

//--------------------------------------------------------------
///	BMPWIN
//==============================================================
enum
{
	WIN_ID_NAME_0 = 0,
	WIN_ID_NAME_1,
	WIN_ID_NAME_2,
	WIN_ID_NAME_3,
	WIN_ID_MAX,
};

#define WIN_NAME1_PX	(3)
#define WIN_NAME1_PY	(8)
#define WIN_NAME2_PX	(23)
#define WIN_NAME2_PY	(1)
#define WIN_NAME3_PX	(23)
#define WIN_NAME3_PY	(3)
#define WIN_NAME4_PX	(23)
#define WIN_NAME4_PY	(5)
#define WIN_NAME_SX		(8)
#define WIN_NAME_SY		(2)
#define WIN_NAME_SIZE	( WIN_NAME_SX * WIN_NAME_SY )

#define WIN_CGX_BASE	(1)
#define WIN_NAME1_CGX	(WIN_CGX_BASE)
#define WIN_NAME2_CGX	(WIN_NAME1_CGX + WIN_NAME_SIZE )
#define WIN_NAME3_CGX	(WIN_NAME2_CGX + WIN_NAME_SIZE )
#define WIN_NAME4_CGX	(WIN_NAME3_CGX + WIN_NAME_SIZE )

static const BMPWIN_DAT c_CatchBmpWinDat[ WIN_ID_MAX ] =
{

	{	// 0:トレーナー名
		BG_FRM_S_TEXT, WIN_NAME1_PX, WIN_NAME1_PY,
		WIN_NAME_SX, WIN_NAME_SY, SUB_FONT_PAL, WIN_NAME1_CGX
	},
	{	// 1:トレーナー名
		BG_FRM_S_TEXT, WIN_NAME2_PX, WIN_NAME2_PY,
		WIN_NAME_SX, WIN_NAME_SY, SUB_FONT_PAL, WIN_NAME2_CGX
	},
	{	// 2:トレーナー名
		BG_FRM_S_TEXT, WIN_NAME3_PX, WIN_NAME3_PY,
		WIN_NAME_SX, WIN_NAME_SY, SUB_FONT_PAL, WIN_NAME3_CGX
	},
	{	// 3:トレーナー名
		BG_FRM_S_TEXT, WIN_NAME4_PX, WIN_NAME4_PY,
		WIN_NAME_SX, WIN_NAME_SY, SUB_FONT_PAL, WIN_NAME4_CGX
	},
};


//--------------------------------------------------------------
///	CAP_ID
//==============================================================
typedef enum {
	CAP_NUM_MAX = 2,	// OBJ Num XX:XX
	CAP_FLAG_MAX  = ENTRY_MEMBER_NUM_MAX,	// 旗の数
	CAP_BUOY_LINE = 2,	// ブイの数(行)
	CAP_BUOY_ROW = 12,	// ブイの数(列)
	CAP_BUOY_MAX = CAP_BUOY_ROW * CAP_BUOY_LINE,

	CAP_ID_TIME_ICON = 0,
	CAP_ID_NUM_HEAD,
	CAP_ID_NUM_END = CAP_ID_NUM_HEAD + CAP_NUM_MAX,
	CAP_ID_FLAG_HEAD = CAP_ID_NUM_END,
	CAP_ID_FLAG_END =  CAP_ID_FLAG_HEAD + CAP_FLAG_MAX,
	CAP_ID_BUOY_HAED = CAP_ID_FLAG_END,
	CAP_ID_BUOY_END = CAP_ID_BUOY_HAED + CAP_BUOY_MAX,
	CAP_ID_MAX = CAP_ID_BUOY_END,
} CAP_ID;

//--------------------------------------------------------------
///	フラッグ座標
//==============================================================
static const POS_DATA g_FlagPos[] =
{
	{ 21*8, 2*8 },	///< 他旗A
	{ 21*8, 4*8 },	///< 他旗B
	{ 21*8, 6*8 },	///< 他旗C
	{  1*8, 9*8 },	///< 自分の旗座標
};

//=============================================================================
/**
 *								構造体定義
 */
//=============================================================================

//--------------------------------------------------------------
///	SUB画面 コントローラー
//==============================================================
typedef struct CATCH_SUB_CNT_tag {
	// [IN]
	PKTHLN_PTR work;
	HEAPID HeapID;
	CATS_SYS_PTR csp;
	CATS_RES_PTR crp;
	GF_BGL_INI* bgl;
	MSGDATA_MANAGER* MsgMan;
	WORDSET* WordSet;
	u8 NetID;
	// [PRIVATE]
	void* PointBgArc;
	NNSG2dScreenData* PointScrnData;
	GF_BGL_BMPWIN Win[ WIN_ID_MAX ];
	CATS_ACT_PTR cap[ CAP_ID_MAX ];
	u8 time_color;	///< 時間OBJの色変化SEQ
	u8 BitLoopCounter; // 表示カンスト数をカウントして表示時に使用
	u16 DispScore;	///< 表示しているスコア値
} CATCH_SUB_CNT;

//=============================================================================
/**
 *							プロトタイプ宣言
 */
//=============================================================================
static CATS_ACT_PTR OBJ_AddCapSub( CATS_SYS_PTR csp, CATS_RES_PTR crp, s16 px, s16 py, u16 anime, u16 pri );
static void CreateBmpWin( CATCH_SUB_CNT_PTR ptr );
static void BG_FillPoint(CATCH_SUB_CNT_PTR ptr, const u8 inPoint);
static void OBJ_CreateTime( CATCH_SUB_CNT_PTR ptr );
static void CreateTeamView( CATCH_SUB_CNT_PTR ptr );
static void OBJ_CreateBuoy( CATCH_SUB_CNT_PTR ptr );
static void OBJ_AllAnimeStop( CATCH_SUB_CNT_PTR ptr );


//-----------------------------------------------------------------------------
/**
 *	@brief	サブ画面管理モジュール生成
 *
 *	@param	CATS_SYS_PTR csp
 *	@param	crp
 *	@param	HeapID
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
CATCH_SUB_CNT_PTR CatchSub_Create( CATS_SYS_PTR csp, CATS_RES_PTR crp, GF_BGL_INI* bgl, MSGDATA_MANAGER* mm, WORDSET* wset, u8 NetID, HEAPID HeapID, PKTHLN_PTR work )
{
	CATCH_SUB_CNT_PTR ptr;

	ptr = sys_AllocMemory( HeapID, sizeof(CATCH_SUB_CNT) );
	MI_CpuClear8( ptr, sizeof(CATCH_SUB_CNT) );

	ptr->csp = csp;
	ptr->crp = crp;
	ptr->NetID = NetID;
	ptr->HeapID = HeapID;
	ptr->bgl = bgl;
	ptr->MsgMan = mm;
	ptr->WordSet = wset;
	ptr->work = work;

	CreateBmpWin( ptr );

	// 時計アイコン
	ptr->cap[ CAP_ID_TIME_ICON ] = OBJ_AddCapSub(
				ptr->csp, ptr->crp, TIME_ICON_POS_X, TIME_ICON_POS_Y,
				NANR_catch_obj_sub_time_icon, PRI_SUB_ICON );

	OBJ_CreateBuoy( ptr );
	OBJ_CreateTime( ptr );

	CreateTeamView( ptr );

	// BGスコア用リソースロード
	ptr->PointBgArc = ArcUtil_ScrnDataGet(ARC_PKTHEV_CATCH, NARC_pkthev_catch_catch_bg_sub_point_lz_NSCR,
						TRUE, &ptr->PointScrnData, ptr->HeapID);

	// 時間初期化
	CatchSub_DispTime( ptr, GAME_TIME/30 );
	// BGスコア初期化
	BG_FillPoint( ptr, 0 );

	return ptr;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	サブ画面管理モジュール削除
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void CatchSub_Delete( CATCH_SUB_CNT_PTR ptr )
{
	int i;

	GF_ASSERT( ptr );

	//スクリーンアーカイブ解放
	sys_FreeMemoryEz(ptr->PointBgArc);

	//BMPWIN開放
	for( i=0; i<WIN_ID_MAX; i++ )
	{
		GF_BGL_BmpWinDel( &ptr->Win[i] );
	}

	//CAP開放
	for( i=0; i<CAP_ID_MAX; i++ )
	{
		GF_ASSERT( ptr->cap[i] );
		CATS_ActorPointerDelete_S( ptr->cap[i] );
	}

	sys_FreeMemoryEz( ptr );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	終了処理
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void CatchSub_Finish( CATCH_SUB_CNT_PTR ptr )
{
	OBJ_AllAnimeStop( ptr );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	スコアを更新
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *	@param	u8 NetID	得点を得たプレイヤーのNetID
 *	@param	Score		通信データ：スコア
 *
 *	@retval	増加量
 */
//-----------------------------------------------------------------------------
u8 CatchSub_UpdateScore( CATCH_SUB_CNT_PTR ptr, u8 NetID, u16 Score )
{
	u16 diff;

	// 自分のスコアのみ反映
	if( NetID == PTFrameGetCurrentID(ptr->work) )
	{
		// 差異があるときのみ更新
		if( Score != ptr->DispScore )
		{
			int disp_score;

			// 回り込み判定
			if( ptr->DispScore > Score )
			{
				ptr->BitLoopCounter++;
			}

			// 7 bitなので1ループにつき + 128
			disp_score = Score + ptr->BitLoopCounter * 128;

#if PM_DEBUG
			GF_ASSERT( disp_score < 1000 );
#endif

			disp_score = MATH_CLAMP( disp_score, 0, 999 );

			BG_FillPoint( ptr, disp_score );

			// 前回との差
			diff = Score - ptr->DispScore;

			// 前回の値を保持
			ptr->DispScore = Score;
		}
	}

	return diff;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	指定チームの加点演出
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *	@param	NetID
 *
 *	@retval	TRUE:更新が行われた
 */
//-----------------------------------------------------------------------------
BOOL CatchSub_AddScore( CATCH_SUB_CNT_PTR ptr, u8 NetID, u16 Score )
{
	GF_ASSERT( ptr );
	GF_ASSERT( NetID < ENTRY_MEMBER_NUM_MAX );

	// 旗アニメ開始
	CATS_ObjectAnimeSeqSetCap(
			ptr->cap[ CAP_ID_FLAG_HEAD + NetID ] ,
			NANR_catch_obj_sub_flag_red_2 + NetID );

	// 自分のスコアのみ反映
	if( NetID == PTFrameGetCurrentID(ptr->work) )
	{
		// 差異があるときのみ更新
		if( Score != ptr->DispScore )
		{
			u16 diff;

			diff = CatchSub_UpdateScore( ptr, NetID, Score );

			// 得点差に応じて効果音を鳴らす
			if( diff == 1 ) {
			} else if( diff == 2 ) {
				Snd_SePitchPlay( SE_THLON_POINT1, THLON_CATCH_PITCH_LV2 );
			} else if (diff == 3 ) {
				Snd_SePitchPlay( SE_THLON_POINT1, THLON_CATCH_PITCH_LV3 );
			} else {
				Snd_SePitchPlay( SE_THLON_POINT1, THLON_CATCH_PITCH_LV4 );
			}

			return TRUE;
		}
	}

	return FALSE;
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *	@param	int inTime
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
void CatchSub_DispTime( CATCH_SUB_CNT_PTR ptr, const int inTime )
{
	u8 sec,sec_t,sec_o;

	//秒計算
	sec = inTime % 100;

	sec_t = sec / 10;
	sec_o = sec % 10;

	// カラーチェンジ
	switch( ptr->time_color )
	{
	case 0 :
		if( sec <= 20 )
		{
			int i;
			for( i=0; i<CAP_NUM_MAX; i++ )
			{
				CATS_ObjectPaletteSetCap( ptr->cap[ CAP_ID_NUM_HEAD + i ], TIME_PAL_OFS+1 );
			}
			ptr->time_color++;
		}
		break;

	case 1 :
		if( sec <= 3 )
		{
			int i;
			for( i=0; i<CAP_NUM_MAX; i++ )
			{
				CATS_ObjectPaletteSetCap( ptr->cap[ CAP_ID_NUM_HEAD + i ], TIME_PAL_OFS+2 );
			}
			ptr->time_color++;
		}
		break;

	case 2 : break;

	default : GF_ASSERT(0);
	}

	//秒を書き換え
	CATS_ObjectAnimeSeqSetCap(ptr->cap[ CAP_ID_NUM_HEAD + 0 ], sec_t + NANR_catch_obj_sub_num_0 );
	CATS_ObjectAnimeSeqSetCap(ptr->cap[ CAP_ID_NUM_HEAD + 1 ], sec_o + NANR_catch_obj_sub_num_0 );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	今ローカル表示している値を取得
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
u16 CatchSub_GetDispScore( CATCH_SUB_CNT_PTR ptr )
{
	u16 DispScore;

	// 7 bitなので1ループにつき + 128
	DispScore = ptr->DispScore + ptr->BitLoopCounter * 128;
	HOSAKA_PRINT("call Get DispScore : %d \n", DispScore );

	return DispScore;
}

//=============================================================================
/**
 *								外部公開関数
 */
//=============================================================================

//=============================================================================
/**
 *								static関数
 */
//=============================================================================

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	CATS_SYS_PTR csp
 *	@param	crp
 *	@param	px
 *	@param	py
 *	@param	anime
 *	@param	pri
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static CATS_ACT_PTR OBJ_AddCapSub( CATS_SYS_PTR csp, CATS_RES_PTR crp, s16 px, s16 py, u16 anime, u16 pri )
{
	TCATS_OBJECT_ADD_PARAM_S prm = {
		0, 0, 0,
		0, 0, 0, NNS_G2D_VRAM_TYPE_2DSUB,
		{ CHR_ID_SUB, PAL_ID_SUB, CEL_ID_SUB, ANM_ID_SUB },
		1, 0,
	};

	CATS_ACT_PTR cap;

	GF_ASSERT(csp);
	GF_ASSERT(crp);

	prm.x = px;
	prm.y = py;
	prm.anm = anime;
	prm.pri = pri;

	cap = CATS_ObjectAdd_S_SubDistance( csp, crp, &prm, OBJ_DISTANCE );
	CATS_ObjectAutoAnimeSetCap( cap, TRUE );

	return cap;
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CreateBmpWin( CATCH_SUB_CNT_PTR ptr )
{
	u8 i;

	GF_ASSERT( ptr );
	GF_ASSERT( ptr->bgl );

	for( i=0; i<WIN_ID_MAX; i++ )
	{
		const BMPWIN_DAT* dat = &c_CatchBmpWinDat[i];

		GF_BGL_BmpWinAddEx( ptr->bgl, &(ptr->Win[i]), dat );
	}

	//先頭キャラをクリア（スクリーンクリアされてるところは、このキャラで埋まる）
	GF_BGL_CharFill( ptr->bgl, BG_FRM_S_TEXT, 0, 1, 0 );

	//システム用フォントパレット転送
	SystemFontPaletteLoad(PALTYPE_SUB_BG, SUB_FONT_PAL*0x20, ptr->HeapID);
}

//-----------------------------------------------------------------------------
/**
 *	@brief	点数のフィル
 *
 *	@param	ptr
 *	@param	u8 inPoint
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void BG_FillPoint(CATCH_SUB_CNT_PTR ptr, const u8 inPoint)
{
	u8 i;
	u8 h,t,o;
	u8 read_x[POINT_DIGI_MAX];
	u8 read_y[POINT_DIGI_MAX];

	//3桁の点数を3つに分解
	h = inPoint / 100;
	t = (inPoint-(h*100)) / 10;
	o = inPoint % 10;

	//データ読み込み位置を算出(数字スクリーンデータに依存)
	read_x[0] = (h%NUMBER_SCR_NUM_W)*POINT_NUMBER_W;
	read_y[0] = (h/NUMBER_SCR_NUM_W)*POINT_NUMBER_H;
	read_x[1] = (t%NUMBER_SCR_NUM_W)*POINT_NUMBER_W;
	read_y[1] = (t/NUMBER_SCR_NUM_W)*POINT_NUMBER_H;
	read_x[2] = (o%NUMBER_SCR_NUM_W)*POINT_NUMBER_W;
	read_y[2] = (o/NUMBER_SCR_NUM_W)*POINT_NUMBER_H;

	for (i=0;i<POINT_DIGI_MAX;i++)
	{
		GF_BGL_ScrWriteFree(ptr->bgl, BG_FRM_S_SCORE,
		POINT_DISP_START_X+(i*POINT_NUMBER_W), POINT_DISP_START_Y,
		POINT_NUMBER_W, POINT_NUMBER_H,
		&ptr->PointScrnData->rawData,
		read_x[i], read_y[i], POINT_NUMBER_W*NUMBER_SCR_NUM_W, POINT_NUMBER_H*NUMBER_SCR_NUM_H );
	}
	GF_BGL_LoadScreenV_Req(ptr->bgl, BG_FRM_S_SCORE);
}

static void OBJ_CreateTime( CATCH_SUB_CNT_PTR ptr )
{
	POS_DATA pos;
	int i;

	for( i=0; i<CAP_NUM_MAX; i++ )
	{
		pos.X = ( TIME_ICON_POS_X + 16 + TIME_CAP_DIFF_X ) + 16 * i;
		pos.Y = TIME_ICON_POS_Y;
		ptr->cap[ CAP_ID_NUM_HEAD + i ] = OBJ_AddCapSub(
				ptr->csp, ptr->crp, pos.X, pos.Y,
				NANR_catch_obj_sub_num_0 + i, PRI_SUB_ICON );

		CATS_ObjectPaletteSetCap( ptr->cap[ CAP_ID_NUM_HEAD + i ], TIME_PAL_OFS );

		// [":"]
//		if( i==2 ){ CATS_ObjectAnimeSeqSetCap( ptr->cap[ CAP_ID_NUM_HEAD + i ], NANR_catch_obj_sub_num_bar ); }
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CreateTeamView( CATCH_SUB_CNT_PTR ptr )
{
	int i;
	u8 cnt = 0;

	GF_ASSERT(ptr);

	// チーム名＆旗
	for( i=0; i<ENTRY_MEMBER_NUM_MAX; i++ )
	{
		POS_DATA pos;
		STRBUF* name_buf;
		u8 win_idx;

		// 自分は特殊表記
		if( i== ptr->NetID )
		{
			win_idx = WIN_ID_NAME_0;

			pos.X = g_FlagPos[3].X;
			pos.Y = g_FlagPos[3].Y;
		}
		// 自分以外の旗を表示
		else
		{
			win_idx = WIN_ID_NAME_1 + cnt;

			pos.X = g_FlagPos[cnt].X;
			pos.Y = g_FlagPos[cnt].Y;
			cnt++;
		}

		name_buf = MyStatus_CreateNameString( PTFrame_GetMyStatus(ptr->work, i), ptr->HeapID );

		// String Print
		GF_BGL_BmpWinDataFill( &ptr->Win[ win_idx ], 0 );
		GF_STR_PrintColor( &ptr->Win[ win_idx ], FONT_SYSTEM, name_buf, 0, 0, MSG_NO_PUT, COL_N_WHITE, NULL );
		GF_BGL_BmpWinOn( &ptr->Win[ win_idx ] );

		STRBUF_Delete( name_buf );

		// OBJ Add
		ptr->cap[ CAP_ID_FLAG_HEAD + i ] = OBJ_AddCapSub(
				ptr->csp, ptr->crp, pos.X, pos.Y,
				NANR_catch_obj_sub_flag_red + i, PRI_SUB_FLAG );
	}
}


//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void OBJ_CreateBuoy( CATCH_SUB_CNT_PTR ptr )
{
	int i,j; // count x, y

	for( j=0; j<CAP_BUOY_ROW; j++ )
	{
		for( i=0; i<CAP_BUOY_LINE; i++ )
		{
			s16 px, py;
			u32 cap_idx;

			cap_idx = CAP_ID_BUOY_HAED + j * CAP_BUOY_LINE + i;

			px = 128;
			px += ( 8 * (4+j) ) * ( i==0 ? 1 : -1 );
			py = 8 + j * 16;

			ptr->cap[ cap_idx ] =
				OBJ_AddCapSub( ptr->csp, ptr->crp, px, py, NANR_catch_obj_sub_buoy, PRI_SUB_BUOY );
			// 海の手前
			CATS_ObjectBGPriSetCap( ptr->cap[ cap_idx ], 3 );
		}
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	オートアニメ停止
 *
 *	@param	CATCH_SUB_CNT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void OBJ_AllAnimeStop( CATCH_SUB_CNT_PTR ptr )
{
	int i;

	for( i=0; i<CAP_ID_MAX; i++ )
	{
		CATS_ObjectAutoAnimeSetCap( ptr->cap[i], FALSE );
	}
}
